﻿using Engine;
using Engine.Audio;
using Engine.Graphics;
using GameEntitySystem;
using System;
using System.Collections.Generic;
using TemplatesDatabase;

namespace Game
{
    /// <summary>
    /// 实体信息管理
    /// </summary>
    public class EntityInfoManager
    {
        public static string[][] ModelTypes = new string[][]
        {
             new string[] { "Body", "Head", "Leg1", "Leg2", "Hand1", "Hand2" }, //人模型
			 new string[] { "Body", "#Neck", "Head", "Leg1", "Leg2", "Leg3", "Leg4" }, //四脚动物模型，#表示可为空
			 new string[] { "Body", "Neck", "Head", "Leg1", "Leg2", "#Wing1", "#Wing2" }, //鸟模型
			 new string[] { "Body", "#Neck", "Head", "Leg1", "Leg2" }, //不飞鸟模型
			 new string[] { "Body",  "Tail1", "Tail2", "#Jaw" }, //鱼模型
		};

        public static Dictionary<string, EntityInfo> EntityInfos = new Dictionary<string, EntityInfo>();

        public static EntityInfo GetEntityInfo(string name)
        {
            if (EntityInfos.TryGetValue(name, out EntityInfo modelInfo))
            {
                return modelInfo;
            }
            return null;
        }

        public static void SetEntityInfos()
        {
            var playerEntityInfo = new EntityInfo
            {
                KeyName = "player",
                EntityName = "MalePlayer",
                DisplayName = "玩家",
                Model = "Models/HumanMale",
                Texture = "Textures/Creatures/HumanMale1",
            };
            var boatEntityInfo = new EntityInfo
            {
                KeyName = "boat",
                EntityName = "Boat",
                DisplayName = "船",
                Model = "Models/Boat",
                Texture = "Textures/Boat",
            };
            EntityInfos.Add(playerEntityInfo.KeyName, playerEntityInfo);
            EntityInfos.Add(boatEntityInfo.KeyName, boatEntityInfo);
            foreach (ValuesDictionary entitiesValuesDictionary in DatabaseManager.EntitiesValuesDictionaries)
            {
                try
                {
                    string name = entitiesValuesDictionary.DatabaseObject.Name.ToLower();
                    if (name == "maleplayer" || name == "femaleplayer") continue;
                    ValuesDictionary valuesDictionary = DatabaseManager.FindValuesDictionaryForComponent(entitiesValuesDictionary, typeof(ComponentCreature));
                    if (valuesDictionary != null)
                    {
                        string value = valuesDictionary.GetValue<string>("DisplayName");
                        if (value.StartsWith("[") && value.EndsWith("]"))
                        {
                            string[] lp = value.Substring(1, value.Length - 2).Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries);
                            value = LanguageControl.GetDatabase("DisplayName", lp[1]);
                        }
                        if (!string.IsNullOrEmpty(value))
                        {
                            ValuesDictionary valuesDictionary2 = DatabaseManager.FindValuesDictionaryForComponent(entitiesValuesDictionary, typeof(ComponentCreatureModel));
                            var modelInfo = new EntityInfo
                            {
                                KeyName = entitiesValuesDictionary.DatabaseObject.Name.ToLower(),
                                EntityName = entitiesValuesDictionary.DatabaseObject.Name,
                                DisplayName = value,
                                Model = valuesDictionary2.GetValue<string>("ModelName"),
                                Texture = valuesDictionary2.GetValue<string>("TextureOverride"),
                            };
                            EntityInfos.Add(modelInfo.KeyName, modelInfo);
                        }
                    }
                }
                catch
                {
                }
            }
            foreach (ValuesDictionary entitiesValuesDictionary in DatabaseManager.EntitiesValuesDictionaries)
            {
                try
                {
                    if (entitiesValuesDictionary.DatabaseObject.Name == "Boat") continue;
                    ValuesDictionary valuesDictionary = DatabaseManager.FindValuesDictionaryForComponent(entitiesValuesDictionary, typeof(ComponentDamage));
                    if (valuesDictionary != null)
                    {
                        ValuesDictionary valuesDictionary2 = DatabaseManager.FindValuesDictionaryForComponent(entitiesValuesDictionary, typeof(ComponentModel));
                        if (valuesDictionary2 != null)
                        {
                            var modelInfo = new EntityInfo
                            {
                                KeyName = entitiesValuesDictionary.DatabaseObject.Name.ToLower(),
                                EntityName = entitiesValuesDictionary.DatabaseObject.Name,
                                DisplayName = entitiesValuesDictionary.DatabaseObject.Name,
                                Model = valuesDictionary2.GetValue<string>("ModelName"),
                                Texture = valuesDictionary2.GetValue<string>("TextureOverride"),
                            };
                            EntityInfos.Add(modelInfo.KeyName, modelInfo);
                        }
                    }
                }
                catch
                {
                }
            }
        }

        public static string GetModelType(Model model)
        {
            List<string> meshs = new List<string>();
            foreach (ModelMesh modelMesh in model.Meshes)
            {
                meshs.Add(modelMesh.Name);
            }
            for (int i = 0; i < ModelTypes.Length; i++)
            {
                bool isSame = true;
                foreach (string mesh in ModelTypes[i])
                {
                    if (mesh.StartsWith("#")) continue;
                    if (!meshs.Contains(mesh))
                    {
                        isSame = false;
                        break;
                    }
                }
                if (isSame)
                {
                    switch (i)
                    {
                        case 0: return "HumanModel";
                        case 1: return "FourLeggedModel";
                        case 2: return "BirdModel";
                        case 3: return "FlightlessBirdModel";
                        case 4: return "FishModel";
                    }
                }
            }
            return "OtherModel";
        }

        public static string GetModelType(string obj)
        {
            Entity entity = DatabaseManager.CreateEntity(GameManager.Project, GetEntityName(obj), true);
            ComponentModel componentModel = entity.FindComponent<ComponentModel>();
            if (componentModel != null)
            {
                return componentModel.GetType().Name.Replace("Component", "");
            }
            return "OtherModel";
        }

        public static string GetModelTypeDisplayName(string modelName)
        {
            switch (modelName)
            {
                case "HumanModel": return "人模型";
                case "FourLeggedModel": return "四脚动物模型";
                case "BirdModel": return "鸟模型";
                case "FlightlessBirdModel": return "不飞鸟模型";
                case "FishModel": return "鱼模型";
            }
            return "其他模型";
        }

        public static string GetEntityName(string obj)
        {
            EntityInfo modelInfo = GetEntityInfo(obj);
            return (modelInfo != null) ? modelInfo.EntityName : obj;
        }

        public static void ChangeModelDisplay(ref ModelWidget modelWidget, string model, string texture)
        {
            modelWidget.Model = ContentManager.Get<Model>(model);
            modelWidget.TextureOverride = ContentManager.Get<Texture2D>(texture);
            var absoluteTransforms = new Matrix[modelWidget.Model.Bones.Count];
            modelWidget.Model.CopyAbsoluteBoneTransformsTo(absoluteTransforms);
            BoundingBox boundingBox = modelWidget.Model.CalculateAbsoluteBoundingBox(absoluteTransforms);
            float x = MathUtils.Max(boundingBox.Size().X, 1.4f * boundingBox.Size().Y, boundingBox.Size().Z);
            modelWidget.ViewPosition = new Vector3(boundingBox.Center().X, 1.5f, boundingBox.Center().Z) + 2.6f * MathUtils.Pow(x, 0.75f) * new Vector3(-1f, 0f, -1f);
            modelWidget.ViewTarget = boundingBox.Center();
            modelWidget.ViewFov = 0.3f;
            modelWidget.AutoRotationVector = Vector3.Zero;
            float n = MathUtils.Clamp(boundingBox.Size().XZ.Length() / boundingBox.Size().Y, 1f, 1.5f);
            modelWidget.Size = new Vector2(modelWidget.Size.Y * n, modelWidget.Size.Y);
        }
    }
}